/*
 * User: ophir
 * Date: Sep 11, 2008
 * Time: 10:39:48 AM
 */
package org.conann.metadata.records;

import static com.google.common.base.Preconditions.checkNotNull;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;

public abstract class Parameter<T> implements AnnotatedElement {

    private final int index;
    private final Class<?> type;
    private T behaviorElement;

    protected Parameter(int index, Class<?> type) {
        this.index = index;
        this.type = type;
    }

    public Class<?> getType() {
        return type;
    }

    public int getIndex() {
        return index;
    }

    @SuppressWarnings({"unchecked"})
    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        checkNotNull(annotationClass);
        for (Annotation annotation : getAnnotations()) {
            if (annotationClass.equals(annotation.annotationType())) {
                return (T) annotation;
            }
        }
        return null;
    }

    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
        checkNotNull(annotationClass);
        return getAnnotation(annotationClass) != null;
    }

    public Annotation[] getDeclaredAnnotations() {
        return getAnnotations();
    }

    protected abstract T getElement();

    protected abstract String getElementName();

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (other == null || getClass() != other.getClass()) {
            return false;
        }
        Parameter<?> otherParam = (Parameter<?>) other;
        return getElement().equals(otherParam.getElement()) && getIndex() == otherParam.getIndex();
    }

    @Override
    public int hashCode() {
        return 31 * getElement().hashCode() + getIndex();
    }

    @Override
    public String toString() {
        return getElementName() + " [" + getIndex() + ']';
    }
}